#pragma once
#include "Epoll.hpp"
#include "SocketEH.hpp"

class EpollReactor
{
private:
    static const int default_one_loop_num = 256;

    void Dispatch(int n)
    {
        for(int i = 0; i < n; i++)
        {
            std::shared_ptr<EventHandler> eh_ptr = _epoll.GetHandler(_ready_events[i].data.fd);
            uint32_t events = _ready_events[i].events;
            if(events & EPOLLERR || events & EPOLLHUP)
                events = (EPOLLIN | EPOLLOUT);

            if(events & EPOLLIN)
                eh_ptr->HandleRecv();
            if(events & EPOLLOUT)
                eh_ptr->HandleSend();
        }
    }
public:
    EpollReactor(int one_loop_num = default_one_loop_num)
        : _isrunning(false)
        , _ready_events(one_loop_num)
    {}
    void Run(int timeout)
    {
        _isrunning = true;
        while(_isrunning)
        {
            int n = _epoll.Wait(_ready_events, timeout);
            if(n > 0)
            {
                LOG(LogLevel::INFO) << "有事件就绪...";
                Dispatch(n);
            }
        }
        _isrunning = false;
    }
    bool RegisterEH(const std::shared_ptr<EventHandler>& event_handler, uint32_t events)
    {
        event_handler->SetMonitor(&_epoll);
        return _epoll.AddEventHandler(event_handler, events);
    }
    ~EpollReactor() {}
private:
    Epoll _epoll;
    bool _isrunning;
    std::vector<epoll_event> _ready_events;
};